﻿namespace DotNetCommon
{
    using DotNetCommon.Extensions;
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Linq;
    using System.Text.RegularExpressions;

    /// <summary>
    /// 提供一组方法来帮助使用<see cref="System.Text.RegularExpressions.Regex"/>。
    /// </summary>
    public sealed class RegexHelper
    {
        private RegexHelper() { }
        #region 电子邮箱格式校验
        private static readonly Regex _emailPrimaryRegex =
            new Regex(@"(@)(.+)$", RegexOptions.Compiled, 200.Milliseconds());

        private static readonly Regex _emailSecondaryRegex =
            new Regex(
                @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
                @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
                RegexOptions.Compiled | RegexOptions.IgnoreCase,
                250.Milliseconds());

        private readonly IdnMapping _idn = new IdnMapping();

        private bool _isValid = true;

        /// <summary>
        ///  包含可以用作正则表达式参数的字符。
        /// </summary>
        private static readonly char[] RegexCharacters =
        {
            'G', 'Z', 'A', 'n', 'W', 'w', 'v', 't', 's', 'S', 'r', 'k', 'f', 'D', 'd', 'B', 'b'
        };

        /// <summary>
        /// 将给定的<paramref name="input"/>判断是否为有效的电子邮件地址。
        /// <see href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format"/>
        /// </summary>
        private bool isValidEmail(string input)
        {
            if (input.IsNullOrEmptyOrWhiteSpace()) { return false; }

            _isValid = true;

            string replaced;
            try
            {
                replaced = _emailPrimaryRegex.Replace(input, DomainMapper);
            }
            catch (RegexMatchTimeoutException)
            {
                return false;
            }

            if (!_isValid) { return false; }

            try
            {
                return _emailSecondaryRegex.IsMatch(replaced);
            }
            catch (RegexMatchTimeoutException)
            {
                return false;
            }

            string DomainMapper(Match match)
            {
                var domainName = match.Groups[2].Value;
                try
                {
                    domainName = _idn.GetAscii(domainName);
                }
                catch (ArgumentException)
                {
                    _isValid = false;
                }
                return match.Groups[1].Value + domainName;
            }
        }
        #endregion

        /// <summary>
        /// 是否是正确的邮箱格式
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        internal static bool IsValidEmail(string input)
        {
            return new RegexHelper().isValidEmail(input);
        }

    }
}